#pragma once
#include <iostream>
#include <pthread.h>
#include "Thread.hpp"
#include "Task.hpp"
#include "LockGuard.hpp"
#include <vector>
#include <queue>
const static int g_nums_default = 5;
template <class T>
class ThreadPool
{
public:
    static ThreadPool<T> *GetOnceTP(int num = g_nums_default)
    {
        if (once_tp_ == nullptr)
        {
            pthread_mutex_lock(&st_mutex);
            if (once_tp_ == nullptr)
            {
                once_tp_ = new ThreadPool<T>(num);
            }
            pthread_mutex_unlock(&st_mutex);
        }
        return once_tp_;
    }
    bool TaskIsEmpty()
    {
        return task_queue_.empty();
    }
    void WaitCond()
    {
        cond_.Wait(mutex_.mutex_);
    }
    T GetTask()
    {
        T t = task_queue_.front();
        task_queue_.pop();
        return t;
    }

    void run() // 将线程池中的线程拿出来去执行任务
    {
        // int i=0;
        for (auto &e : tpool_)
        {
            e->Start();
           // std::cout << "启动成功" << std::endl;
            // std::cout<<i++<<std::endl;
        }
        // std::cout<<"jiesu"<<std::endl;//调试
    }
    ~ThreadPool()
    {
        for (auto &i : tpool_)
        {
            i->Join();
            delete i;
        }
    }
    static void *routine(void *args) // 执行任务函数
    //void *routine(void *args) // 执行任务函数
    {
        // std::cout<<"进入rou"<<std::endl;
        ThreadData *td = (ThreadData *)args;
        ThreadPool<T> *tp = (ThreadPool<T> *)(td->args_);
        while (true)
        {
            // std::cout<<"r-->while"<<std::endl;
            T task; // 创建任务对象
            {
                LockGuard locgd(&(tp->mutex_));
                while (tp->TaskIsEmpty())
                    tp->WaitCond();
                // 获取任务
                task = tp->GetTask();
            }
            // 处理任务
            // std::cout<<"处理任务"<<std::endl;
            task(td->name_);
            // std::cout<<"处理完成"<<std::endl;
        }
    }
    void PushTask(const T &task) // 放入任务
    {
        LockGuard locgd(&mutex_);
        // std::cout<<"push begin"<<std::endl;
        task_queue_.push(task);
        // std::cout<<"push end"<<std::endl;
        cond_.Awaken();
        // std::cout<<"等待完成"<<std::endl;
    }
    // 类内声明
    static ThreadPool<T> *once_tp_;
    static pthread_mutex_t st_mutex;

private:
    ThreadPool(int threadnums = g_nums_default)
        : num_(threadnums),
          mutex_(new pthread_mutex_t()),
          cond_(new pthread_cond_t())
    {
        for (int i = 0; i < num_; i++)
        {
            tpool_.push_back(new Thread(i + 1, routine, this)); // 传递this指针，可以让静态函数访问类内成员
        }
    }
    ThreadPool(const ThreadPool<T> &pt) = delete;
    const ThreadPool<T> &operator=(const ThreadPool<T> &pt) = delete;

private:
    std::vector<Thread *> tpool_; // 存放线程
    std::queue<T> task_queue_;    // 存放任务
    int num_;                     // 线程个数
    Mutex mutex_;                 // 锁
    Cond cond_;                   // 条件变量
};
// 类外定义
template <class T>
ThreadPool<T> *ThreadPool<T>::once_tp_ = nullptr;
template <class T>
pthread_mutex_t ThreadPool<T>::st_mutex = PTHREAD_MUTEX_INITIALIZER;